package com.redoor.app.stake.auth.controller;

import com.alibaba.fastjson.JSONObject;
import com.redoor.app.stake.auth.commons.StakeApplicationStatus;
import com.redoor.app.stake.auth.model.BaseUser;
import com.redoor.app.stake.auth.model.controllerModel.SSOUserInfo;
import com.redoor.app.stake.auth.model.controllerModel.UserInfo;
import com.redoor.app.stake.auth.model.serviceModel.LoginUserBean;
import com.redoor.app.stake.auth.service.BaseUserService;
import com.redoornetwork.framework.core.response.ResponseResult;
import com.redoornetwork.framework.core.response.ResultGenerator;
import com.redoornetwork.framework.data.redis.util.RedisUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.crazycake.shiro.SerializeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import sunbox.core.hsf.api.SysManageService;
import sunbox.core.hsf.vo.OperatorItem;
import sunbox.core.vo.api.OpenAPIResponse;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;


/**
 * Created by wangjunlei on 2018/1/24.
 */

@RestController
@RequestMapping("/login")
public class LoginController {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private SysManageService sysManageService;

    @Autowired
    private BaseUserService baseUserService;

    @Autowired
    RedisUtils redisUtils;
    @Autowired
    private RedisSessionDAO redisSessionDAO;
    /**
     * sso登录验证
     * @param info
     * @return
     * @throws IOException
     */
    @GetMapping("/ssologin")
    public ModelAndView ssologin(SSOUserInfo info) throws IOException {
        String tokken = info.getToken();
        String url = info.getUrl();
        try {
            OpenAPIResponse resultJson = sysManageService.login(tokken, "", "", "");
            OperatorItem op = null;
            if("success".equalsIgnoreCase(resultJson.getResult())){
                // 操作
                Object data = resultJson.getData();
                op = (OperatorItem) data;
            }
            if(op == null){
                return new ModelAndView("error").addObject("exception",ResultGenerator.generatorFail(StakeApplicationStatus.LOGIN_AUTH_FAILED));
            }
            String oType = op.getSysRoleType();
            if (!"4".equalsIgnoreCase(oType)) {
                return new ModelAndView("error").addObject("exception",ResultGenerator.generatorFail(StakeApplicationStatus.LOGIN_AUTH_NOROLE));
            }

            String pwd = op.getPassword();
            //密码为空默认使用大写用户名+后缀
            if(StringUtils.isEmpty(pwd)){
                pwd = op.getUserName();
            }
            //sha256加密
            String password = new StringBuffer(DigestUtils.md5DigestAsHex(pwd.toString().getBytes("utf8"))).toString() ;
            op.setPassword(password);

            baseUserService.addOperatorItemToUser(op);

            Subject subject = SecurityUtils.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken(op.getUserName(), op.getPassword());
            subject.login(token);

        } catch (Exception ex) {
            logger.error(ex.getLocalizedMessage(),ex);
            return new ModelAndView("error").addObject("exception",ResultGenerator.generatorFail(StakeApplicationStatus.OTHER_EXCEPTION));
        }

        ModelAndView mv = new ModelAndView("redirect:/index.html");
        return mv;
    }

    /**
     * 登录方法
     * @param userInfo
     * @return
     */
    @RequestMapping(value = "/ajaxLogin", method = RequestMethod.POST)
    @ResponseBody
    public ResponseResult ajaxLogin(@RequestBody UserInfo userInfo) {
        JSONObject jsonObject = new JSONObject();
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(userInfo.getUsername(), userInfo.getPassword());
        try {
            subject.login(token);

            jsonObject.put("token", subject.getSession().getId());
            jsonObject.put("msg", "登录成功");
            return ResultGenerator.generatorSuccess(jsonObject);
        } catch (IncorrectCredentialsException e) {
            jsonObject.put("msg", "密码错误");
        } catch (LockedAccountException e) {
            jsonObject.put("msg", "登录失败，该用户已被冻结");
        } catch (AuthenticationException e) {
            jsonObject.put("msg", "该用户不存在");
        } catch (Exception e) {
            jsonObject.put("msg", "其他错误");
        }
        return ResultGenerator.generatorFail(StakeApplicationStatus.LOGIN_AUTH_FAILED,jsonObject);
    }


    @GetMapping("/getCurrentUser")
    public ResponseResult getCurrentUser(HttpSession session) {
        BaseUser user = baseUserService.getShiroUser(session.getId());
        return ResultGenerator.generatorSuccess(user);
    }


    @RequestMapping(value = "/logout", method = RequestMethod.GET)
    public ModelAndView logout(ServletRequest request) throws IOException {
        Subject subject = SecurityUtils.getSubject();
        // 如果已经登录，则跳转到管理首页
        if(subject.getPrincipal() != null){
            subject.logout();
            request.getServletContext().removeAttribute("userSession");
            redisSessionDAO.delete(subject.getSession());
        }
        ModelAndView mv = new ModelAndView("redirect:/login.html");

        if(redisUtils.hHasKey("BASE_PROP","VENDERSYSTEMURL")){
            mv.setViewName("redirect:" + redisUtils.hget("BASE_PROP","VENDERSYSTEMURL").toString());
        }
        return mv;
    }
}
